/**
 * The contents of this file are subject to the license and copyright detailed in the LICENSE and NOTICE files at the root of the source tree and available online at
 * http://www.askosi.org/license.html
 */
package be.destin.skos.core;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

public class MetadataValue {
	
    /** log4j logger */
    private static Logger log = Logger.getLogger(MetadataValue.class);

	private ArrayList<MetadataValueToken> tokens = null;
	boolean pureCoded = false;

	public MetadataValue(SkosManager skosManager, String aValue, SchemeInterface defaultScheme, List<? extends SchemeInterface> conceptSchemes, List<NotationScheme> notationSchemes) {
		super();
		parse(skosManager, aValue, defaultScheme, conceptSchemes, notationSchemes);
	}

	/**
	 * @return the value
	 */
	public String getValue() {
		StringBuffer aValue = new StringBuffer();
		for (MetadataValueToken token : tokens) {
			aValue.append(token.toString());
		}
		return aValue.toString();
	}

	/**
	 * @return the value with separator between tokens
	 */
	public String toString() {
		StringBuffer aValue = new StringBuffer();
		for (MetadataValueToken token : tokens) {
			Concept aConcept = token.getConcept();
			if (aConcept != null) {
				aValue.append("[");
				aValue.append(aConcept.getScheme_About());
				aValue.append("]");
				aValue.append(token.isBlankAfter()? "+":"");
			}
			else {
				aValue.append(token.getValue());
				aValue.append("|");
				aValue.append(token.isBlankAfter()? "+":"");
			}
		}
		return aValue.toString();
	}

	/**
	 * @return the tokens
	 */
	public ArrayList<MetadataValueToken> getTokens() {
		return tokens;
	}

	/**
	 * @param tokens the tokens to set
	 */
	public void setTokens(ArrayList<MetadataValueToken> tokens) {
		this.tokens = tokens;
	}
	
	private void parse(SkosManager skosManager, String aValue, SchemeInterface defaultScheme, List<? extends SchemeInterface> conceptSchemes, List<NotationScheme> notationSchemes) {
		if (skosManager == null) return;
		tokens = new ArrayList<MetadataValueToken>();
		char[] aValueArray = aValue.toCharArray();
		int i = 0;
		int precI = 0;
		boolean inWord = false;
		MetadataValueToken token = null;
		while (i < aValueArray.length) {
			char c = aValueArray[i];
			if (Character.isJavaIdentifierPart(c)) {
				if (!inWord) {
					if (i > precI) {
						String toAdd = new String(aValueArray,precI,i-precI);
						if (token != null && token.getConcept() == null) {
							token.value = token.value+(token.isBlankAfter()?" ":"")+toAdd;
							token.setBlankAfter(false);
						}
						else {
							token = new MetadataValueToken(toAdd, false, false);
							tokens.add(token);
						}
					}
					inWord = true;
					precI = i;
				}
			} else {
				if (inWord) {
					if (i > precI) {
						String aWord = new String(aValueArray,precI,i-precI);
						Concept aConcept = skosManager.getScheme_Concept(aWord, defaultScheme, conceptSchemes, notationSchemes);
						if (aConcept != null) {
							token = new MetadataValueToken(aConcept,c == ' ');
							tokens.add(new MetadataValueToken(aConcept,c == ' '));
						}
						else {
							if (token != null && token.getConcept() == null) {
								token.value = token.value+(token.isBlankAfter()?" ":"")+aWord;
								token.setBlankAfter(c == ' ');
								token.setWord(true);
							}
							else {
								token = new MetadataValueToken(aWord,true,c == ' '); 
								tokens.add(token);
							}
						}
					}
					inWord = false;
					precI = i;
					if (c == ' ') precI++;
				}
			}
			i++;
		}
		if (aValueArray.length > precI) {
			if (inWord) {
				String aWord = new String(aValueArray,precI,aValueArray.length-precI);
				Concept aConcept = skosManager.getScheme_Concept(aWord, defaultScheme, conceptSchemes,notationSchemes);
				if (aConcept != null ) {
					tokens.add(new MetadataValueToken(aConcept,false));
				}
				else {
					if (token != null && token.getConcept() == null) {
						token.value = token.value+(token.isBlankAfter()?" ":"")+aWord;
						token.setBlankAfter(false);
						token.setWord(true);
					}
					else {
						token = new MetadataValueToken(aWord,true,false); 
						tokens.add(token);
					}
				}
			} else {
				String toAdd = new String(aValueArray,precI,i-precI);
				if (token != null && token.getConcept() == null) {
					token.value = token.value+(token.isBlankAfter()?" ":"")+toAdd;
					token.setBlankAfter(false);
				}
				else {
					token = new MetadataValueToken(toAdd, false, false);
					tokens.add(token);
				}
			}
		}
		pureCoded = true;
		for (MetadataValueToken aToken : tokens) {
			if (aToken.getConcept() == null && aToken.isWord()) pureCoded = false;
		}
		log.debug(this.toString());
	}

	/**
	 * @return the pureCoded
	 */
	public boolean isPureCoded() {
		return pureCoded;
	}

	/**
	 * @param pureCoded the pureCoded to set
	 */
	public void setPureCoded(boolean pureCoded) {
		this.pureCoded = pureCoded;
	}
}
